fn main() {
    // case1 只定义枚举类型，不定义枚举值
    #[derive(Debug)]
    enum IpAddrKind {
        V4,
        V6,
    }
    // case1
    struct IpAddr {
        kind: IpAddrKind,
        address: String,
    }
    
    let local = IpAddr {
        kind: IpAddrKind::V4,
        address: String::from("127.0.0.1"),
    };

    let loopback = IpAddr {
        kind: IpAddrKind::V6,
        address: String::from("::1"),
    };

    let v4 = IpAddrKind::V4;
    let v6 = IpAddrKind::V6;
    println!("{:?}", v4);
    println!("{:?}", v6);

    // case2 同时定义枚举类型和枚举值
    enum IpAddrKind2 {
        V4(String),
        V6(String),
    }
    // 效果等同于14-17行，不需要额外的结构体了
    let local = IpAddrKind2::V4(String::from("127.0.0.1"));
    let loopback = IpAddrKind2::V6(String::from("::1"));

    // case3 枚举可以处理不同类型和数量数据
    enum IpAddrKind3 {
        V4(u8, u8, u8, u8),
        V6(String),
    }
    let local = IpAddrKind3::V4(127, 0, 0, 1);
    let loopback = IpAddrKind3::V6(String::from("::1"));

    // case4 枚举成员可以是各种类型
    enum Message{
        Quit,
        Move {x: i32, y: i32},
        Write(String),
        ChangeColor(i32, i32, i32),
    }

    // case5 枚举中可以定义方法
    impl Message {
        fn call(&self) {
            // todo
        }
    }

    // Option
    let five = 5;
    let some_number = Some(5);
    let some_char = Some('e');
    let absent_number: Option<i32> = None;
    // 此时编译不通过
    // println!("{}", five + some_number)
    // Option 移除包装获取值
    println!("{}", five + some_number.unwrap());

    // case6 模式匹配
    enum Coin {
        Penny,
        Nickel,
        Dime,
        Quarter,
    }

    fn value_in_cents(coin: Coin) -> u8 {
        match coin {
            Coin::Penny => {
                    println!("这是便士");
                    1
            } // 多行用{}，可以不带;
            Coin::Nickel => 5, // 单行代码可以不带{}
            Coin::Dime => 10,
            Coin::Quarter => 25,
        }
    }

    println!("{}", value_in_cents(Coin::Penny));

    // case7 模式匹配枚举值
    #[derive(Debug)]
    enum UsState {
        Alabama,
        Alaska,
    }
    enum Coin2 {
        Penny,
        Nickel,
        Dime,
        Quarter(UsState),
    }
    fn value_in_cents2(coin: Coin2) -> u8 {
        match coin {
            Coin2::Penny => {
                println!("这是便士");
                1
            } // 多行用{}，可以不带;
            Coin2::Nickel => 5, // 单行代码可以不带{}
            Coin2::Dime => 10,
            Coin2::Quarter(state) => {
                println!("state quarter from {state:?}");
                25
            }
        }
    }

    println!("{}", value_in_cents2(Coin2::Quarter(UsState::Alabama)));

    // case8 option match
    fn plus_one(x: Option<i32>) -> Option<i32> {
        match x {
            None => None,
            Some(i) => Some(i + 1),
        }
    }
    let x = Some(5);
    let x = plus_one(x);
    println!("{}", x.is_some());

    let x = plus_one(None);
    println!("{}", x.is_some());

    // case8 最后一个即为通配分支
    let dice_roll = 9;
    match dice_roll {
        1 => {
            println!("this is 1");
        }
        10 => {
            println!("this is 10");
        }
        // 放在最后
        x => {
            println!("{} 不做处理", x);
        }
    }

    // case 9, 如果不需要使用到变量可以用_代替
    match dice_roll {
        1 => {
            println!("this is 1");
        }
        10 => {
            println!("this is 10");
        }
        // 放在最后
        _ => {
            println!("skip");
        }
    }
    
    // case10 if let
    let x = Some(5);
    if let Some(value) = x {
        println!("{value}");
    }
}
